package com.ww.scm.service;

import java.util.List;

import org.apache.shiro.SecurityUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.ww.core.exception.ServiceException;
import com.ww.core.orm.Page;
import com.ww.core.orm.PropertyFilter;
import com.ww.scm.entity.sec.Group;
import com.ww.scm.entity.sec.User;
import com.ww.scm.repository.sec.GroupRepository;
import com.ww.scm.repository.sec.UserRepository;

/**
 * 安全相关实体的管理类,包括用户和权限组.
 * 
 */

@Service
@Transactional
public class AccountManager {

	private static Logger logger = LoggerFactory.getLogger(AccountManager.class);
	
	private static final String SUPERVISOR_ID="1";

	private UserRepository userRepository;
	private GroupRepository groupRepository;
	private ShiroDbRealm shiroRealm;

	//-- User Manager --//
	@Transactional(readOnly = true)
	public User getUser(String id) {
		return userRepository.get(id);
	}

	public void saveUser(User entity) {
		userRepository.save(entity);
		shiroRealm.clearCachedAuthorizationInfo(entity.getLoginName());
	}

	/**
	 * 删除用户,如果尝试删除超级管理员将抛出异常.
	 */
	public void deleteUser(String id) {
		if (isSupervisor(id)) {
			logger.warn("操作员{}尝试删除超级管理员用户", SecurityUtils.getSubject().getPrincipal());
			throw new ServiceException("不能删除超级管理员用户");
		}
		userRepository.delete(id);
	}

	/**
	 * 判断是否超级管理员.
	 */
	private boolean isSupervisor(String id) {
		return SUPERVISOR_ID.equals(id);
	}

	/**
	 * 使用属性过滤条件查询用户.
	 */
	@Transactional(readOnly = true)
	public Page<User> findUser(final Page<User> page, final List<PropertyFilter> filters) {
		return userRepository.findPage(page, filters);
	}

	@Transactional(readOnly = true)
	public User findUserByLoginName(String loginName) {
		return userRepository.findUniqueBy("loginName", loginName);
	}

	/**
	 * 检查用户名是否唯一.
	 *
	 * @return loginName在数据库中唯一或等于oldLoginName时返回true.
	 */
	@Transactional(readOnly = true)
	public boolean isLoginNameUnique(String newLoginName, String oldLoginName) {
		return userRepository.isPropertyUnique("loginName", newLoginName, oldLoginName);
	}

	//-- Group Manager --//
	@Transactional(readOnly = true)
	public Group getGroup(String id) {
		return groupRepository.get(id);
	}

	@Transactional(readOnly = true)
	public List<Group> getAllGroup() {
		return groupRepository.getAll("id", true);
	}

	public void saveGroup(Group entity) {
		groupRepository.save(entity);
		shiroRealm.clearAllCachedAuthorizationInfo();
	}

	public void deleteGroup(String id) {
		groupRepository.delete(id);
		shiroRealm.clearAllCachedAuthorizationInfo();
	}

	@Autowired(required = false)
	public void setShiroRealm(ShiroDbRealm shiroRealm) {
		this.shiroRealm = shiroRealm;
	}
	
	@Autowired(required = false)
	public void setUserRepository(UserRepository userRepository) {
		this.userRepository = userRepository;
	}
	
	@Autowired(required = false)
	public void setGroupRepository(GroupRepository groupRepository) {
		this.groupRepository = groupRepository;
	}
}
